////////////////////////////////////////////////////////////////////////////////////////////////////
/// @file   CollabRCBotUnitTests\TestVariableTreeNode.h
///
/// @brief  Defines unit tests for the CollabRC::Bot::AI::VariableTreeNode class
////////////////////////////////////////////////////////////////////////////////////////////////////

#include <cxxtest/TestSuite.h>
#include "../CollabRCBot/VariableTreeNode.h"

using CollabRC::Bot::AI::VariableTreeNode;
using CollabRC::Bot::AI::ComputationalTreeNode;

////////////////////////////////////////////////////////////////////////////////////////////////////
/// @class  TestVariableTreeNode
///
/// @brief  Test suite for testing CollabRC::Bot::AI::VariableTreeNode
///
/// @author Matthew P. Del Buono
/// @date   12/21/2009
////////////////////////////////////////////////////////////////////////////////////////////////////
class TestVariableTreeNode : public CxxTest::TestSuite
{
public:
    /**
     * Tests that the VariableTreeNode is accurately following the value
     */
    void TestCompute()
    {
        // Start off with one value
        float v = 4;
        VariableTreeNode<float> node(v);
        TS_ASSERT_EQUALS(node.Compute(), v);
        
        // Change it to another value
        v = 5;
        TS_ASSERT_EQUALS(node.Compute(), v);
    }

    /**
     * Operates like TestCompute() but uses an integer to ensure the
     * casting mechanism is functioning
     */
    void TestCast()
    {
        // Start off with one value
        int v = 4;
        VariableTreeNode<int> node(v);
        TS_ASSERT_EQUALS(node.Compute(), v);

        // Change it to another
        v = 5;
        TS_ASSERT_EQUALS(node.Compute(), v);
    }

    /**
     * Tests the cloning mechanism
     */
    void TestClone()
    {
        float v = 4;
        VariableTreeNode<float> node(v);
        ComputationalTreeNode *clone = node.Clone();

        TS_ASSERT_EQUALS(clone->Compute(), v);
        v = 5;
        TS_ASSERT_EQUALS(clone->Compute(), v);

        delete clone;
    }

    /**
     * Ensures that the branch depth is always 1
     */
    void TestBranchDepth()
    {
        float v;
        VariableTreeNode<float> node(v);
        TS_ASSERT_EQUALS(node.GetBranchDepth(), 1);
    }

    /**
     * Checks that the random branch is simply a clone of the
     * current branch. This must be true because it is the only branch.
     */
    void TestGetRandomBranch()
    {
        float v = 4;
        VariableTreeNode<float> node(v);
        const ComputationalTreeNode& branch = node.GetRandomBranch(0);
        TS_ASSERT_EQUALS(&branch, &node);

        // Going beyond the branch depth should also yield the same result
        const ComputationalTreeNode& branch2 = node.GetRandomBranch(1);
        TS_ASSERT_EQUALS(&branch2, &node);
    }

    /**
     * Tests the Mutate() operation on a VariableTreeNode. These nodes
     * should not be able to mutate so this should be identical to a Clone()
     * operation.
     */
    void TestMutate()
    {
        float v = 4;
        VariableTreeNode<float> node(v);
        ComputationalTreeNode* copy = node.Mutate(0);

        // Verify it still operates as normal
        TS_ASSERT_EQUALS(copy->Compute(), v);
        v = 5;
        TS_ASSERT_EQUALS(copy->Compute(), v);

        delete copy;
    }
};